
#ifndef _TTG_SERVICES_SERVICE_
#define _TTG_SERVICES_SERVICE_
#include "Common/Definitions.h"

#include "Common/Structures.h"
#include <vector>
#include <string>

namespace ttg
{
	namespace services
	{
		//Represents object, which can be started/updated/stopped and depends on other objects.
		class Service :public ttg::structures::NamedObject
		{
			private:
				bool is_started;
				bool is_updatable;
				std::vector<std::string> dependencies;			//names of objects, that are used by this object
				std::vector<std::string> dependents;			//names of objects, that uses this object.
				ttg::structures::Loopback<bool> on_starting;	//notifies, that service is going to start.
				ttg::structures::Loopback<bool> on_start;		//notifies, that service has been started.
				ttg::structures::Loopback<bool> on_stopping;	//notifies, that service is going to stop.
				ttg::structures::Loopback<bool> on_stop;		//notifies, that service has been stopped.
			private:
				//Returns names of objects, that uses this object.
				//Should be called by ServiceBase only.
				inline std::vector<std::string> &getDependents()
						{ return dependents; }
			protected:
				//Creates object with given name.
				//"deps" defines names of used objects, splitted by space: "name1 name2 name3".
				Service(const char *name, const char *deps, bool is_updatable = true);
				//Starts objects without checks.
				virtual void startUnSafe(std::vector<Service *> &deps, const char *params) = 0;
				//Stops objects without checks.
				virtual void stopUnSafe() = 0;
				//Updates current object without checks.
				virtual void updateUnSafe(float step)
						{ /*nothing*/ }
				//Performs registration for current service (in service base).
				void makeRegistration();
			public:
				//Returns names of objects, that are used by this object.
				inline std::vector<std::string> &getDependencies()
						{ return dependencies; }
				//Returns true, if object has been started.
				inline bool isStarted() const
						{ return is_started; }
				//Returns true, if object can be updated.
				inline bool isUpdatable() const
						{ return is_updatable; }
				//Notifies, that service is going to start.
				inline ttg::structures::Loopback<bool> &onStarting()
				{ return on_starting; }
				//Notifies, that service has been started.
				inline ttg::structures::Loopback<bool> &onStart()
				{ return on_start; }
				//Notifies, that service is going to stop.
				inline ttg::structures::Loopback<bool> &onStopping()
				{ return on_stopping; }
				//Notifies, that service has been stopped.
				inline ttg::structures::Loopback<bool> &onStop()
				{ return on_stop; }
				//Starts current object.
				//"deps" should contain used objects.
				//"params" - object specific params (or NULL).
				void start(std::vector<Service *> &deps, const char *params = NULL);
				//Stops current object.
				void stop();
				//Updates current object.
				void update(float step);
				virtual ~Service()
						{ /*nothing*/ }
			friend class ServiceBase;
		};
	}
}

#endif
